package com.cn.gmall.cart.service.impl;

import com.cn.gmall.cart.service.CartInfoService;
import com.cn.gmall.common.constant.RedisConst;
import com.cn.gmall.common.util.DateUtil;
import com.cn.gmall.model.cart.CartInfo;
import com.cn.gmall.model.list.SearchParam;
import com.cn.gmall.model.product.SkuInfo;

import com.cn.gmall.product.client.ProductFeignClient;

import org.apache.commons.io.input.ReaderInputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.nio.file.NotLinkException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CartInfoServiceImpl implements CartInfoService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private ProductFeignClient productFeignClient;

    /**
     * 获取选中状态的购物车列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<CartInfo> getCartCheckedList(String userId) {
        String cartKey = getCartKey(userId);
//        获取操作数据的对象
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = boundHashOperations.values();
//       选取 选中的购物项
        List<CartInfo> checkCartInFotList = cartInfoList.stream().filter(cartInfo -> {
//         进入详情页 重新确定商的价格
            cartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId()));

            return cartInfo.getIsChecked().intValue() == 1;
        }).collect(Collectors.toList());

        return checkCartInFotList;
    }

    /**
     * 删除购物车 选中的购物项
     *
     * @param userId
     */
    @Override
    public void deleteIsChecked(String userId) {
//获取 当前userId 选中的购物项

        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(getCartKey(userId));
//        获取所有的购物项
        List<CartInfo> cartInfoList = boundHashOperations.values();
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            for (CartInfo cartInfo : cartInfoList) {
//.intValue() 将数据转成基本类型 int
                if (cartInfo.getIsChecked().intValue() == 1) {
//      删除选中的购物项
                    boundHashOperations.delete(cartInfo.getSkuId().toString());
                }
            }


        }


    }

    /***
     * 删除购物项
     * @param skuId
     * @param
     */
    @Override
    public void deleteCart(String skuId, String userId) {
//删除
        redisTemplate.boundHashOps(getCartKey(userId)).delete(skuId);
    }

    /**
     * 更新选中状态
     *
     * @param skuId
     * @param isChecked
     */
    @Override
    public void checkCart(Long skuId, Integer isChecked, String userId) {
//获取当前key
        String cartKey = this.getCartKey(userId);
//        获取redis数据对象
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(cartKey);
//       获取对象数据(redis 里面用string类型作为主键存储)
        CartInfo cartInfo = (CartInfo) boundHashOperations.get(skuId.toString());
//     设置状态
        cartInfo.setIsChecked(isChecked);
//        更新
        boundHashOperations.put(skuId.toString(), cartInfo);

    }

    /***
     * 合并
     *           1.用户未登录 不需要合并
     *           2.用户已登录
     *                 2.1 临时id里面购物车为空 只查登录的用户购物车
     *                 2.2 临时购物车里不为空 合并登录用户和临时用户的购物车
     *                       2.2.1 怎么合并?
     *                         a . 若是临时id的购物车和用户购物车存在箱相同的购物项 用户购物车购物项数量=(用户购物量+临时购物量)
     *                         b . 不同的购物项直接把临时购物车的购物项添加到 用户购物车里面
     */
    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {
//        购物车
        List<CartInfo> noLoginCartList = new ArrayList<>();


        if (!StringUtils.isEmpty(userTempId)) {
//            临时id组成的redis存储key
            String cartKey = getCartKey(userTempId);
//            获取数据
            noLoginCartList = redisTemplate.boundHashOps(cartKey).values();
        }
//判断用户是否登录
        if (StringUtils.isEmpty(userId)) {
//            未登录 且临时购物车不为空 -----合并
            if (!CollectionUtils.isEmpty(noLoginCartList)) {
                noLoginCartList.sort((o1, o2) -> {
                    return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
                });
            }
//            返回排序购物车列表
            return noLoginCartList;
        } else {

//用户已登录
            String cartKey = this.getCartKey(userId);
//            登录用户的购物车
            BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(cartKey);
//      判断是否合并
            if (!CollectionUtils.isEmpty(noLoginCartList)) {
//                遍历未登录的购物车
                for (CartInfo cartInfo : noLoginCartList) {
//                    用户购物车包含了临时购物车的购物项

                    if (boundHashOperations.hasKey(cartInfo.getSkuId().toString())) {
//                        增加用户购物车的购物项的数量
//                        根据skuId获取当前的cartInfo
                        CartInfo sameCartInfo = (CartInfo) boundHashOperations.get(cartInfo.getSkuId().toString());
//                        临时购物车购物项数量和用户购物车的购物项数量
                        sameCartInfo.setSkuNum(sameCartInfo.getSkuNum() + cartInfo.getSkuNum());
                        sameCartInfo.setUpdateTime(new Date()); //更新时间
                        sameCartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId())); //更新实时价格
//                     选中 临时购物车没有选中则不选中
                        if (cartInfo.getIsChecked() == 1) {
                            sameCartInfo.setIsChecked(1);
                        }
//               更新redis
                        boundHashOperations.put(cartInfo.getSkuId().toString(), sameCartInfo);
                    } else {
//                        临时购物车在用户购物车不同的购物项 直接添加到用户购物车里面
                        cartInfo.setUserId(userId); //替换临时用户id
                        cartInfo.setCreateTime(new Date());
                        cartInfo.setUpdateTime(new Date());
                        boundHashOperations.put(cartInfo.getSkuId().toString(), cartInfo);
                    }
                }
//                合并完成 删除临时的购物车
                redisTemplate.delete(getCartKey(userTempId).toString());

            }

//            获取登录后的购物车
            List<CartInfo> userCartLIst = boundHashOperations.values();

            if (CollectionUtils.isEmpty(userCartLIst)) {
//                临时购物车和用户购物车都为空
                return new ArrayList<>();
            }
//          用户购物车不为空  排序
            userCartLIst.sort(new Comparator<CartInfo>() {
                @Override
                public int compare(CartInfo o1, CartInfo o2) {
                    return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
                }
            });
//            返回排序后的购物车
            return userCartLIst;
        }
    }

/***
 * 查询购物车列表  未合并
 * @param userId
 * @param userTempId
 * @return
 */
/*    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {
        List<CartInfo> cartInfoList = null;
//       临时id加入的购物项
        if (!StringUtils.isEmpty(userTempId)) {
            BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(this.getCartKey(userTempId));
            cartInfoList = boundHashOperations.values();
        }
//如果临时id里面加入购物项 会在登录后如果用户购物车非空 会被覆盖

        if (!StringUtils.isEmpty(userId)) {
            BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(this.getCartKey(userId));
            cartInfoList = boundHashOperations.values();

        }
//        根据加入购物车的时间 进行排序
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            cartInfoList.sort((o1, o2) -> {
//Calendar.SECOND 日历的类型
                return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
            });
        }

        return cartInfoList;
    }*/

    /***
     * 加入购物车
     * @param userId
     * @param skuId
     * @param skuNum
     *
     * 判断商品是否是第一次添加
     * 商品第一次添加,构建该商品
     * 购物车已经存在该商品 继续添加数量 加一
     */
    @Override
    public void addToCart(String userId, Long skuId, Integer skuNum) {

//        创建存储key
        String cartKey = this.getCartKey(userId);
/**
 *     获取当前的购物车项
 */
        /**
         *     对某一个数据redis操作 用opsForHash 多个用boundHashOps生成一个BoundHashOperations对象
         *     用对象的操作方式进行存取数据
         */

        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(cartKey);
//        判断
        CartInfo cartInfo = null;
        if (boundHashOperations.hasKey(skuId.toString())) {
//            已经有该商品了 加数量
            cartInfo = (CartInfo) boundHashOperations.get(skuId.toString());
            cartInfo.setSkuNum(cartInfo.getSkuNum() + skuNum);
//更新时间
            cartInfo.setUpdateTime(new Date());
            cartInfo.setSkuPrice(productFeignClient.getSkuPrice(skuId));

        } else {
//第一次添加
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);

            cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);
//            加入时价格
            cartInfo.setCartPrice(skuInfo.getPrice());
            cartInfo.setSkuNum(skuNum);
            cartInfo.setSkuName(skuInfo.getSkuName());
            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());
//            实时价格
            cartInfo.setSkuPrice(skuInfo.getPrice());

        }

        boundHashOperations.put(skuId.toString(), cartInfo);
        boundHashOperations.expire(RedisConst.USER_CART_EXPIRE, TimeUnit.SECONDS);

    }

    /**
     * 存储的cartKey
     *
     * @param userId
     * @return
     */
    private String getCartKey(String userId) {
//        此时 userId 可能是临时id或用户id

//user:id:cart
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }
}
